package scala.examples.fs;

import scala.util.parsing.combinator.lexical.StdLexical

object tester extends SyntaxIsMappable with Parser with Typers with Application {
  def parseAndTypeCheck(s: String) = {
    phrase(term)(new lexical.Scanner(s)) match {
      case Success(tm, _ ) => Console.println(Console.BLUE+tm.toString+": "+Console.RED+EmptyContextTyper.of(tm).toString+Console.BLACK) 
      case f => Console.println(f)
    }
  }
  
  Console.println(phrase(term)(new lexical.Scanner("val x : Unit = new Unit in x")).toString)
  Console.println(phrase(term)(new lexical.Scanner("val x : Unit = new Unit in x.ab.d.e.f")).toString)
  Console.println(phrase(term)(new lexical.Scanner("val x : Unit = new Unit in ERROR")).toString)


  
/*  parseAndTypeCheck("""
new () { u =>
  trait Any () { anySelf => }  
  
}
""")*/

/*  parseAndTypeCheck("""
new () { u =>
  trait Any () { anySelf => }  
  trait Boolean (u.Any) { boolSelf =>
  }
  
  val false: u.Boolean = new u.Boolean
  val true: u.Boolean = new u.Boolean
  
  trait List (u.Any) { listSelf =>
    type t
    def isEmpty(): u.Boolean
  }
  
  trait Cons (u.List) { consSelf =>
    val hd: consSelf.t
    val tl: (u.List) {x=> type t = consSelf.t }
    def isEmpty(): u.Boolean = u.false
  }  
  trait Nil (u.List) { nilSelf =>
    def isEmpty(): u.Boolean = u.true
  }    
}
""")*/

/* would need virtual classes for this:   
in Boolean: type if <: (u.Any) { ifSelf =>
   type t
   def apply(then: (u.Function0){x => type arg=ifSelf.t}, else: (u.Function0){x => type arg=ifSelf.t}): ifSelf.t
} 
//  if(b) t: T else f: T --> (new (b.if){type t=T}).apply(t, f)
// Well-Formedness: no abstract types in concrete classes
*/

/*  Console.println(phrase(term)(new lexical.Scanner("val x : Unit = new Unit in x.ab()")).toString)
  Console.println(phrase(term)(new lexical.Scanner("val x : Unit = new Unit in x.ab().d")).toString)
  Console.println(phrase(term)(new lexical.Scanner("val x : Unit = new Unit in x")).toString)
*/
   
 /* val Success(testast, _) = phrase(term)(new lexical.Scanner("val x : Unit = new (Unit){this => def a(arg: Unit, arg2: Unit) : Unit = arg} in x"))
  Console.println(testast.toString)
   
  
  testast match {
    case Let(tp, tm, u : UnderBinder[Name, Term]) => u.binder.substitute(u.binder(0), Name("y"))
  }
  
  Console.println("after replacing x by y:\n"+testast.toString) */
}
